package com.lysj.bhp.borrowing.service;

import com.lysj.bhp.approve.domain.ApproveRecord;
import com.lysj.bhp.borrowing.base.BorrowingContent;
import com.lysj.bhp.borrowing.domain.BorrowingAccount;
import com.lysj.bhp.borrowing.domain.BorrowingInstallment;
import com.lysj.bhp.borrowing.domain.BorrowingRecord;
import com.lysj.bhp.borrowing.domain.CreditFile;
import com.lysj.bhp.user.domain.User;
import com.lysj.bhp.user.util.MyWallet;
import com.lysj.bhp.util.random.FormatUtil;
import com.lysj.bhp.util.sms.MoYunSMSUtil;
import com.lysj.bhp.util.web.ParamUtil;
import com.lysj.bhp.util.web.Resp;
import com.lysj.bhp.wallet.domain.BhpcWallet;
import com.lysj.bhp.wallet.domain.BitCoinWallet;
import com.lysj.bhp.wallet.domain.EthereumWallet;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional
public class LoanMoneyService extends BorrowingContent {

    @Resource
    MyWallet myWallet;

    public Resp loadMoney(BorrowingRecord borrowingRecord) throws Exception {

        //创建分期记录
        BorrowingInstallment borrowingInstallment = createBorrowingInstallment(borrowingRecord.getBorrowingRecordId(), borrowingRecord.getUserId());
        //判定用户借款利率类型:1:按天,2：按月
        List<BorrowingInstallment> borrowingInstallmentList = new LinkedList<>();
        //每日需归还利息
        BigDecimal totalInterest = new BigDecimal(BigInteger.ZERO);
        //总计应该还金额
        BigDecimal totalMoney = new BigDecimal(BigInteger.ZERO);
        //Map
        Map<Integer,BigDecimal> returnMoneyResult = new HashMap<>();

        if (1 == borrowingRecord.getRateType()) {
            //初始化还款时间
            borrowingInstallment.setBeginRepaymentDate(FormatUtil.getDayStartDay(FormatUtil.addDay(new Date(), borrowingRecord.getDeadline())));
            borrowingInstallment.setEndRepaymentDate(FormatUtil.getDayEndDay(FormatUtil.addDay(new Date(), borrowingRecord.getDeadline())));
            //每天还款利息
            totalInterest = borrowingInterestDay(borrowingRecord.getBorrowingMoney(), borrowingRecord.getInterest());
            //还款方式: 1:到期还本付息,2:等额本息,3:先息后本
            switch (borrowingRecord.getRefundWay()) {
                case 1:
                    borrowingInstallment.setNper(1);
                    borrowingInstallment.setBeginRepaymentDate(FormatUtil.getDayStartDay(FormatUtil.addDay(new Date(),1)));
                    borrowingInstallment.setReturnMoney(borrowingRecord.getBorrowingMoney());
                    borrowingInstallment.setNormalRepaymentDate(FormatUtil.getDaySeventeDay(borrowingInstallment.getEndRepaymentDate()));
                    borrowingInstallment.setReturnDividend(totalInterest.multiply(new BigDecimal(borrowingRecord.getDeadline()).setScale(8,BigDecimal.ROUND_UP)));
                    totalMoney = totalMoney.add(borrowingInstallment.getReturnMoney().add(borrowingInstallment.getReturnDividend()));
                    borrowingInstallmentRepository.save(borrowingInstallment);
                    break;
                case 2:
                    //每日还款本金
                    returnMoneyResult = installmentOfThePrincipal(borrowingRecord.getBorrowingMoney(),borrowingRecord.getDeadline());
                    for (int i = 1; i <= borrowingRecord.getDeadline(); i++) {
                        borrowingInstallment = createBorrowingInstallment(borrowingRecord.getBorrowingRecordId(), borrowingRecord.getUserId());
                        //调用方法生成借贷期数、开始时间、结束时间。
                        createBorrowingInstallment(borrowingInstallment, i);
                        //实际还款金额(每日还款利息+每日还款本金)
                        borrowingInstallment.setReturnMoney(returnMoneyResult.get(i));
                        borrowingInstallment.setReturnDividend(totalInterest);
                        totalMoney = totalMoney.add(borrowingInstallment.getReturnMoney().add(borrowingInstallment.getReturnDividend()));
                        borrowingInstallmentRepository.save(borrowingInstallment);
                    }
                    break;
                case 3:
                    for (int i = 1; i < borrowingRecord.getDeadline(); i++) {
                        borrowingInstallment = createBorrowingInstallment(borrowingRecord.getBorrowingRecordId(), borrowingRecord.getUserId());
                        //调用方法生成借贷期数、开始时间、结束时间。
                        createBorrowingInstallment(borrowingInstallment, i);
                        //实际还款金额(每日还款利息)
                        borrowingInstallment.setReturnMoney(new BigDecimal(BigInteger.ZERO));
                        borrowingInstallment.setReturnDividend(totalInterest);
                        totalMoney = totalMoney.add(borrowingInstallment.getReturnMoney().add(borrowingInstallment.getReturnDividend()));
                        borrowingInstallmentRepository.save(borrowingInstallment);
                    }
                    borrowingInstallment = createBorrowingInstallment(borrowingRecord.getBorrowingRecordId(), borrowingRecord.getUserId());
                    //调用方法生成借贷期数、开始时间、结束时间。
                    createBorrowingInstallment(borrowingInstallment, borrowingRecord.getDeadline());
                    //实际还款金额(每日还款利息+借款本金)
                    borrowingInstallment.setReturnMoney(borrowingRecord.getBorrowingMoney());
                    borrowingInstallment.setReturnDividend(totalInterest);
                    totalMoney = totalMoney.add(borrowingInstallment.getReturnMoney().add(borrowingInstallment.getReturnDividend()));
                    borrowingInstallmentRepository.save(borrowingInstallment);
                    break;
                default:
                    break;
            }
        } else if (2 == borrowingRecord.getRateType()) {
            //类型为月模式下所使用的参数第一期的时间
            Date monthBeginTime = FormatUtil.addDay(new Date(), 1);
            BigDecimal returnMoney = borrowingRecord.getBorrowingMoney();
            totalInterest = borrowingInterestMonth( returnMoney, borrowingRecord.getInterest());
            switch (borrowingRecord.getRefundWay()) {
                case 1:
                    borrowingInstallment.setNper(1);
                    borrowingInstallment.setBeginRepaymentDate(FormatUtil.getDayStartDay(monthBeginTime));
                    borrowingInstallment.setEndRepaymentDate(FormatUtil.getEndYesterday(FormatUtil.getNaturalMonth(monthBeginTime, borrowingRecord.getDeadline())));
                    borrowingInstallment.setNormalRepaymentDate(FormatUtil.getDaySeventeDay(borrowingInstallment.getEndRepaymentDate()));
                    borrowingInstallment.setReturnMoney(returnMoney);
                    borrowingInstallment.setReturnDividend(totalInterest.multiply(new BigDecimal(borrowingRecord.getDeadline())).setScale(8,BigDecimal.ROUND_UP));
                    totalMoney = totalMoney.add((borrowingInstallment.getReturnMoney().add(borrowingInstallment.getReturnDividend())).setScale(8,BigDecimal.ROUND_HALF_UP));
                    borrowingInstallmentRepository.save(borrowingInstallment);
                    break;
                case 2:
                    returnMoneyResult = installmentOfThePrincipal(borrowingRecord.getBorrowingMoney(),borrowingRecord.getDeadline());
                    for (int i = 1; i <= borrowingRecord.getDeadline(); i++) {
                        borrowingInstallment = createBorrowingInstallment(borrowingRecord.getBorrowingRecordId(), borrowingRecord.getUserId());
                        //调用月类型模式下，生成期数，开始时间，结束时间，期数
                        createBorrowingInstallment(borrowingInstallment, monthBeginTime, i);
                        borrowingInstallment.setReturnMoney(returnMoneyResult.get(i));
                        borrowingInstallment.setReturnDividend(totalInterest);
                        totalMoney = totalMoney.add(borrowingInstallment.getReturnMoney().add(borrowingInstallment.getReturnDividend()));
                        borrowingInstallmentRepository.save(borrowingInstallment);
                    }
                    break;
                case 3:
                    for (int i = 1; i < borrowingRecord.getDeadline(); i++) {
                        borrowingInstallment = createBorrowingInstallment(borrowingRecord.getBorrowingRecordId(), borrowingRecord.getUserId());
                        createBorrowingInstallment(borrowingInstallment, monthBeginTime, i);
                        borrowingInstallment.setReturnMoney(new BigDecimal(BigInteger.ZERO));
                        borrowingInstallment.setReturnDividend(totalInterest);
                        totalMoney = totalMoney.add(borrowingInstallment.getReturnMoney().add(borrowingInstallment.getReturnDividend()));
                        borrowingInstallmentRepository.save(borrowingInstallment);
                    }
                    borrowingInstallment = createBorrowingInstallment(borrowingRecord.getBorrowingRecordId(), borrowingRecord.getUserId());
                    createBorrowingInstallment(borrowingInstallment, monthBeginTime, borrowingRecord.getDeadline());
                    borrowingInstallment.setReturnMoney(returnMoney);
                    borrowingInstallment.setReturnDividend(totalInterest);
                    totalMoney = totalMoney.add(borrowingInstallment.getReturnMoney().add(borrowingInstallment.getReturnDividend()));
                    borrowingInstallmentRepository.save(borrowingInstallment);
                    break;
                default:
                    break;
            }
        }
        borrowingRecord.setStatus(2);//还款中
        borrowingRecord.setCheckStatus(3);//放款成功
        //创建信用档案 有的话更新档案
        CreditFile creditFile = creditFileRepository.findByUserIdAndWalletType(borrowingRecord.getUserId(), borrowingRecord.getBorrowingType());
        if (ParamUtil.isBlack(creditFile)) {
            creditFile = new CreditFile();
            creditFile.setUserId(borrowingRecord.getUserId());
            creditFile.setWalletType(borrowingRecord.getBorrowingType());
            //笔数
            creditFile.setBorrowingAmount(1);
            creditFile.setPayOffAmount(0);
            creditFile.setAdvanceAmount(0);
            creditFile.setAdvanceBalance(new BigDecimal(BigInteger.ZERO));
            creditFile.setPunctualAmount(0);
            creditFile.setLateAmount(0);
            creditFile.setOverduePayOffAmount(0);
            creditFile.setOverduePayOffBalance(new BigDecimal(BigInteger.ZERO));
            creditFile.setOverdueNoRepayAmount(0);
            creditFile.setOverdueNoRepayBalance(new BigDecimal(BigInteger.ZERO));
            //资产
            creditFile.setBorrowingBalance(borrowingRecord.getBorrowingMoney());
            creditFile.setRepaidBalance(new BigDecimal(BigInteger.ZERO));
            creditFile.setReturnedBalance(totalMoney);
        } else {
            creditFile.setBorrowingAmount(creditFile.getBorrowingAmount() + 1);
            creditFile.setBorrowingBalance(creditFile.getBorrowingBalance().add(borrowingRecord.getBorrowingMoney()));
            creditFile.setReturnedBalance(creditFile.getReturnedBalance().add(totalMoney));
        }
        creditFileRepository.save(creditFile);
        borrowingRecordRepository.save(borrowingRecord);
        //把借款资产打到对应用户的钱包上
        makeLoans(borrowingRecord);
        //增加流水记录
        BorrowingAccount borrowingAccount = new BorrowingAccount();
        borrowingAccount.setUserId(borrowingRecord.getUserId());
        borrowingAccount.setPostAccountId(1L);
        borrowingAccount.setDealMoney(borrowingRecord.getBorrowingMoney());
        borrowingAccount.setAccountType(1);//借款状态
        borrowingAccount.setWalletType(borrowingRecord.getBorrowingType());
        borrowingAccount.setCreateDate(new Date());
        borrowingAccountRepository.save(borrowingAccount);
        String borrowType = "BTC";
        if (borrowingRecord.getBorrowingType().equals(20)) {
            borrowType = "ETH";
        }
        if (borrowingRecord.getBorrowingType() == 100) {
            borrowType = "BHPC";
        }
        //短信内容
        String message = "【BHP】尊敬的BHP用户：您好，您的账户所申请"+borrowingRecord.getBorrowingMoney().setScale(5,BigDecimal.ROUND_HALF_UP)+borrowType+"款项于"+FormatUtil.dateToString2(new Date())+"到账，请您核对好资金，祝您生活愉快！";
        //获取用户手机号码
        User user = userRepository.findByUserId(borrowingRecord.getUserId());
        if (!"86".equals(user.getAreaCode())) {
            message = "【BHP】Dear BHP user: Your applied "+borrowingRecord.getBorrowingMoney().setScale(5,BigDecimal.ROUND_HALF_UP)+borrowType+" asset from BHP financial product is arriving in your account on "+FormatUtil.dateToString2(new Date())+", please check the balance carefully. Hope you have a wonderful day!";
        }
        MoYunSMSUtil.sendNotice(user.getPhone(),user.getAreaCode(),message);
        return new Resp("放款成功!");
    }


    /**
     * @author drj
     * @date 2018/8/17 17:01
     * @Description:生成借款明细:抬头固定部分
     */
    public BorrowingInstallment createBorrowingInstallment(Long borrowingRecordId, Long userId) {
        BorrowingInstallment borrowingInstallment = new BorrowingInstallment();
        borrowingInstallment.setBorrowingRecordId(borrowingRecordId);
        borrowingInstallment.setUserId(userId);
        borrowingInstallment.setDefaultMoney(new BigDecimal(0));
        borrowingInstallment.setDefaultState(2);
        borrowingInstallment.setBlacklistId(new Long(0));
        return borrowingInstallment;
    }

    /**
     * @author zwj
     * @date 2018-08-20 10:33
     * @Description:生成借款明细:月生成开始还款，结束还款时间
     */
    public void createBorrowingInstallment(BorrowingInstallment borrowingInstallment, Date monthBeginTime, Integer nper) throws Exception {
        borrowingInstallment.setNper(nper);
        borrowingInstallment.setBeginRepaymentDate(FormatUtil.getDayStartDay(FormatUtil.getNaturalMonth(monthBeginTime, nper - 1)));
        borrowingInstallment.setEndRepaymentDate(FormatUtil.getEndYesterday(FormatUtil.getNaturalMonth(monthBeginTime, nper)));
        borrowingInstallment.setNormalRepaymentDate(FormatUtil.getDaySeventeDay(FormatUtil.getEndYesterday(FormatUtil.getNaturalMonth(monthBeginTime, nper))));
    }

    /**
     * @author zwj
     * @date 2018-08-20 14:09
     * @Description:生成借款明细:日生成开始还款，结束还款时间
     */
    public void createBorrowingInstallment(BorrowingInstallment borrowingInstallment, Integer nper) {
        //借贷期数
        borrowingInstallment.setNper(nper);
        //初始化还款时间
        Date beginTime = FormatUtil.getDayStartDay(FormatUtil.addDay(new Date(), nper));
        Date endTime = FormatUtil.getDayEndDay(FormatUtil.addDay(new Date(), nper));
        borrowingInstallment.setBeginRepaymentDate(beginTime);
        borrowingInstallment.setNormalRepaymentDate(FormatUtil.getDaySeventeDay(endTime));
        borrowingInstallment.setEndRepaymentDate(endTime);
    }


    /**
     * @author drj
     * @date 2018/8/17 16:31
     * @Description：计算天标利息: 借款本金*年利率/365*(借款到期日期-借款计息日期)
     */
    public BigDecimal borrowingInterestDay( BigDecimal money, BigDecimal interestRate) {
        BigDecimal interest = new BigDecimal(BigInteger.ZERO);
        interest = money.multiply(interestRate.divide(new BigDecimal(100)).divide(new BigDecimal("365"), 18, BigDecimal.ROUND_HALF_UP)).setScale(8,BigDecimal.ROUND_HALF_UP);
        return interest;
    }

    /**
     * @author zwj
     * @date 2018-08-20 09:13
     * @Description:计算月标利息： 借款本金*年利率/12（期数）
     */
    public BigDecimal borrowingInterestMonth( BigDecimal money, BigDecimal interestRate) {
        BigDecimal interset = new BigDecimal(BigInteger.ZERO);
        interset = money.multiply(interestRate.divide(new BigDecimal(100)).divide(new BigDecimal("12"), 18, BigDecimal.ROUND_HALF_UP)).setScale(8,BigDecimal.ROUND_HALF_UP);
        return interset;
    }

    /**
     * @author drj
     * @date 2018/8/17 16:31
     * @Description:计算两个日期间隔天数
     */
    public Long getDay(Date beginDate, Date endDate) {
        Long beginTime = beginDate.getTime();
        Long endTime = endDate.getTime();
        Long diff = endTime - beginTime;
        Long oneDay = 24 * 60 * 60 * 1000L; //一天的时间搓
        if (diff % oneDay == 0) {
            return diff / oneDay;
        } else {
            return (diff / oneDay) + 1L;
        }
    }

    /**
     * @author zwj
     * @date 2018-08-22 09:08
     * @Description:给用户对应钱包放款:1.用户Id,2.所借金额,3.所借钱包类型
     */
    public void makeLoans(BorrowingRecord borrowingRecord) throws Exception {
      switch (borrowingRecord.getBorrowingType()) {
        case 10:
            BitCoinWallet bitCoinWallet = bitcoinWalletRepository.findByUserId(borrowingRecord.getUserId());
            User user = userRepository.findByUserId(borrowingRecord.getUserId());
            if (null == bitCoinWallet) {
                bitCoinWallet = (BitCoinWallet) myWallet.createBitWallet(borrowingRecord.getUserId(), user.getEmail()).getObj();
            }
            bitCoinWallet.setAvailBalance(bitCoinWallet.getAvailBalance().add(borrowingRecord.getBorrowingMoney()));
            bitCoinWallet.setBalance(bitCoinWallet.getBalance().add(borrowingRecord.getBorrowingMoney()));
            bitcoinWalletRepository.save(bitCoinWallet);
            break;
        case 20:
            EthereumWallet ethereumWallet = ethereumWalletRepository.findByUserId(borrowingRecord.getUserId());
            if (null == ethereumWallet) {
                ethereumWallet = (EthereumWallet) myWallet.createEthWallet(borrowingRecord.getUserId()).getObj();
            }
            ethereumWallet.setAvailBalance(ethereumWallet.getAvailBalance().add(borrowingRecord.getBorrowingMoney()));
            ethereumWallet.setBalance(ethereumWallet.getBalance().add(borrowingRecord.getBorrowingMoney()));
            ethereumWalletRepository.save(ethereumWallet);
            break;
        case 100:
            BhpcWallet bhpcWallet = bhpcWalletRepository.findByUserId(borrowingRecord.getUserId());
            if (null == bhpcWallet) {
                bhpcWallet = myWallet.createBhpcWallet(borrowingRecord.getUserId());
            }
            bhpcWallet.setAvailBalance(bhpcWallet.getAvailBalance().add(borrowingRecord.getBorrowingMoney()));
            bhpcWallet.setBalance(bhpcWallet.getBalance().add(borrowingRecord.getBorrowingMoney()));
            bhpcWalletRepository.save(bhpcWallet);
            break;
        }
    }
    /**
     * @author drj
     * @date 2018-09-14 10:43
     * @@Description:本金按依据计算
     */
    public Map<Integer,BigDecimal> installmentOfThePrincipal(BigDecimal money,Integer deadline) {
        //取余运算 results[0]商  results[1]余数
        BigDecimal[] results = money.divideAndRemainder(BigDecimal.valueOf(deadline));
        BigDecimal leftAmount=new BigDecimal(BigInteger.ZERO);
        //本期金额
        BigDecimal returnMoney;
        //Map容器
        Map<Integer,BigDecimal> result = new HashMap<>();
        for (int i = 1; i < deadline; i++) {
            returnMoney = money.divide(new BigDecimal(deadline),8,BigDecimal.ROUND_HALF_UP);
            result.put(i,returnMoney);
            leftAmount=leftAmount.add(returnMoney);
        }
        //如果余数等于0
        if (results[1].compareTo(new BigDecimal(BigInteger.ZERO)) == 0) {
            result.put(deadline,results[0]);
        }else{
            result.put(deadline,money.subtract(leftAmount));
        }
        return result;
    }
}
